home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
clipper
/
nfsrc21.zip
/
CINT86.C
< prev
next >
Wrap
Text File
|
1991-08-15
|
9KB
|
230 lines
/*
* File......: CINT86.C
* Author....: Ted Means
* Date......: $Date: 15 Aug 1991 23:08:32 $
* Revision..: $Revision: 1.2 $
* Log file..: $Logfile: E:/nanfor/src/cint86.c_v $
*
* This function is an original work by Ted Means and is placed in the
* public domain.
*
* Modification history:
* ---------------------
*
* $Log: E:/nanfor/src/cint86.c_v $
*
* Rev 1.2 15 Aug 1991 23:08:32 GLENN
* Forest Belt proofread/edited/cleaned up doc
*
* Rev 1.1 14 Jun 1991 03:48:42 GLENN
* Just corrected some typos in the documentation.
*
* Rev 1.0 27 May 1991 13:22:36 GLENN
* Initial revision.
*
*
* $DOC$
* $FUNCNAME$
* FT_INT86()
* $CATEGORY$
* DOS/BIOS
* $ONELINER$
* Execute a software interrupt
* $SYNTAX$
* FT_INT86( <nInterruptNumber>, <aRegisterValues> ) -> lResult
* $ARGUMENTS$
* <nInterruptNumber> is the interrupt to execute.
*
* <aRegisterValues> is an array that contains values to be loaded
* into the various CPU registers. The correspondence between
* registers and array elements is as follows:
*
* aElement[1] == AX register
* aElement[2] == BX register
* aElement[3] == CX register
* aElement[4] == DX register
* aElement[5] == SI register
* aElement[6] == DI register
* aElement[7] == BP register
* aElement[8] == DS register
* aElement[9] == ES register
* aElement[10] == Flags register
* $RETURNS$
* .T. if all parameters valid and the function was able
* to execute the desired interrupt.
* .F. if invalid parameters passed.
*
* In addition, the array elements will contain whatever values were in
* the CPU registers immediately after the interrupt was executed. If
* either of the string parameters were altered by the interrupt, these
* changes will be reflected as well.
* $DESCRIPTION$
* It is occasionally useful to be able to call interrupts directly from
* Clipper, without having to write a separate routine in C or ASM. This
* function allows you that capability.
*
* Given Clipper's high-level orientation, this function is necessarily
* somewhat messy to use. First, declare an array of ten elements to
* hold the eight values for the CPU registers and two string parameters.
* Then initialize the array elements with the values that you want the
* CPU registers to contain when the interrupt is executed. You need not
* initialize all the elements. For example, if the interrupt requires
* you to specify values for AX, DX, and DS, you would only need to
* initialize elements 1, 4, and 8.
*
* Once you have done the required register setup, call FT_INT86(),
* passing the interrupt number and the register array as parameters.
* The function will load the CPU with your specified values, execute the
* interrupt, and then store the contents of the CPU registers back into
* your array. This will allow you to evaluate the results of the
* interrupt.
*
* Some interrupt services require you to pass the address of a string in
* a pair of registers. This function is capable of handling these sorts
* of situations, but it will take a little work on your part. If you need
* to pass a string that uses the DS register, store the string in element
* 8; if you need to pass a string that uses the ES register, store the
* string in element 9. FT_INT86() will detect that you've supplied a
* string instead of a numeric value and will behave accordingly.
*
* That takes care of obtaining the segment portion of the pointer. To
* specify which register is to contain the offset, use the values REG_DS
* and REG_ES which are defined in the FTINT86.CH file. When one of these
* values is found in an array element, it alerts FT_Int86() to use the
* offset portion of a pointer instead of a numeric value. REG_DS tells
* FT_Int86() to use the offset of the string in element 8, while REG_ES
* tells FT_Int86() to use the offset of the string in element 9.
*
* All the CPU registers are sixteen bits in size. Some, however, are
* also split into two 8-bit registers. This function is only capable of
* receiving and returning registers that are 16 bits in size. To split
* a 16-bit register into two 8-bit values, you can use the
* pseudo-functions HighByte() and LowByte(), contained in the .CH file.
*
* To alter an 8-bit number so it will appear in the high-order byte of a
* register when passed to the FT_INT86() function, use the MakeHI()
* pseudo-function contained in the .CH file.
*
* This function is a shell for __ftint86(), which is written in assembler
* and does the actual work of executing the interrupt. __ftint86() is
* callable from C, so feel free to incorporate it into any C routines
* for which it might be useful. The source for __ftint86() can be found
* in the file AINT86.ASM.
* $EXAMPLES$
*
* * This example shows how to call the DOS "create file" service. Take
* * special note of how to set up string parameters.
*
* #include "FTINT86.CH"
*
* local aRegs[10] && Declare the register array
* aRegs[ AX ] := makehi(60) && DOS service, create file
* aRegs[ CX ] := 0 && Specify file attribute
*
* * Pay attention here, this is crucial. Note how to set up the string
* * so it appears in DS:DX.
*
* aRegs[ DS ] := "C:\MISC\MYFILE.XXX"
* aRegs[ DX ] := REG_DS
* FT_INT86( 33, aRegs) && Make the call to the DOS interrupt
*
*
* * This example shows how to call the DOS "get current directory"
* * service. This one also uses a string parameter, but note that it
* * uses a different offset register.
*
* #include "FTINT86.CH"
*
* local aRegs[10]
* aRegs[ AX ] := makehi(71)
* aRegs[ DX ] := 0 // Choose default drive
*
* * This service requires a 64-byte buffer whose address is in DS:SI. DOS
* * will fill the buffer with the current directory.
*
* aRegs[ DS ] := space(64)
* aRegs[ SI ] := REG_DS
* FT_INT86( 33, aRegs)
*
* ? aRegs[ DS ] // Display the directory name
*
*
*
* * For the sake of completeness, here's an example that doesn't use a
* * string. This one changes the video mode.
*
* #include "FTINT86.CH"
*
* local aRegs[10]
*
* aRegs[ AX ] := 16 && Choose hi-res graphics
* FT_INT86( 16, aRegs)
* $INCLUDE$
* FTINT86.CH
* $END$
*/
#include "extend.h"
#include "cint86.h"
CLIPPER FT_Int86(void)
{
auto struct CPUREGS regs;
auto unsigned int i;
auto char * dsptr = NULL;
auto char * esptr = NULL;
if ( (PCOUNT == 2) && ISNUM(1) && ISARRAY(2) )
{
if ( _parinfa(2, 8) & CHARACTER )
{
_storclen(NULL, _parclen(2, 8), 2, 8);
dsptr = _parc(2, 8);
regs.ds = *((unsigned int *)(&dsptr) + 1);
}
else
regs.ds = _parni(2, 8);
if ( _parinfa(2, 9) & CHARACTER )
{
_storclen(NULL, _parclen(2, 9), 2, 9);
esptr = _parc(2, 9);
regs.es = *((unsigned int *)(&esptr) + 1);
}
else
regs.es = _parni(2, 9);
for (i = 1; i <= 7; i++)
{
if ( _parinfa(2, i) & LOGICAL )
if ( _parl(2, i) )
*(((unsigned int *)(®s)) + i - 1) = *(unsigned int *)&dsptr;
else
*(((unsigned int *)(®s)) + i - 1) = *(unsigned int *)&esptr;
else
*(((unsigned int *)(®s)) + i - 1) = _parni(2, i);
}
__ftint86( _parni(1), ®s);
for (i = 1; i <= 7; i++)
_storni(*(((u